package com.sean.iphoneAppWorkspace;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.AsyncTask;
import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.widget.LinearLayout;

public class DragWorkspace extends LinearLayout implements OnLongClickListener {
	
	public static final String TAG = "DragWorkspace";
	
	private int mRow = 4;
	private int mColumn = 4;
	/** 子View的大小*/
	private int mChildSize = 120;
	
	/** 保存子View的坐标*/
	private int mChildCoordinates[][] = new int[mRow * mColumn][2];
	
	/** 拖曳左右滚动的容差大小,默认为10px*/
	private static final int TRIGGER_SCROLL_SIZE = 20;
	/** 滚屏延时时间*/
	private static final int SCROLL_SCREEN_DELAY = 5000;
	/** 拖动时调整位置的时间间隔*/
	private static final int DRAG_DELAY = 1500;
	
	private Workspace mWorkspace;

	private List<DragItemView> mChildViews;
	private DragItemView mDragItemView;
	private List<DragLayout> mDragLayouts;
	
	private List<DataVo> mChildData;
	
	private boolean mIsShake;
	private int mShakeDelay = 10;
	
	private Vibrator mVibrator;
	
	/** 标识是否正在拖动控件*/
	private boolean mIsDraging;
	
	/** 是否处于滚屏延时时期*/
	private boolean mIsSocrollDelay;
	
	/** 拖曳的类型*/
	private int mDragAction;
	
	/** 拖动的鼠标坐标*/
	private float mTouchOffsetX;
	private float mTouchOffsetY;
	
	/** 图像的长跟宽*/
	private float mBitmapWidth;
	private float mBitmapHeight;
	
	/** 拖动图标的缩略图*/
	private Bitmap mDragBitmap;
	/** 画笔*/
	private Paint mDragPaint;
	
	private boolean mIsFirst = true;
	private int mLastScreenIndex;
	
	private CheckPostionThread mCheckPostionThread;
	
	public DragWorkspace(Context context, List<DataVo> data) {
		super(context);
		mVibrator = (Vibrator) ((Activity)context).getApplication().getSystemService(Service.VIBRATOR_SERVICE);
		
		mWorkspace = new Workspace(context);
		
		mChildData = data;
		int dataSize = mChildData.size();
		int layoutCount = dataSize / (mRow * mColumn);
		if(dataSize % (mRow * mColumn) != 0) {
			layoutCount ++;
		}
		mDragLayouts = new ArrayList<DragLayout>(layoutCount);
		mChildViews = new ArrayList<DragItemView>(dataSize);
		DragLayout dragLayout = null;
		DragItemView dragItemView = null;
		for(int i = 0; i < layoutCount; i ++) {
			dragLayout = new DragLayout(context, mChildSize, mChildCoordinates);
			mDragLayouts.add(dragLayout);
			
			int count = mRow * mColumn;
			if(mRow * mColumn * (i + 1) > dataSize) {
				count = dataSize - mRow * mColumn * i;
			}
			
			Log.e(TAG, "COUNT : " + count);
			
			for(int j = 0; j < count ; j ++) {
				DataVo dataVo = mChildData.get(mRow * mColumn * i + j);
				dragItemView = new DragItemView(context, dataVo, mChildSize);
				dragItemView.setOnLongClickListener(this);
				mChildViews.add(dragItemView);
				dragLayout.addView(dragItemView);
			}
			
			mWorkspace.addView(dragLayout);
		}
		this.addView(mWorkspace, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
		
		mInvalidateTask.execute();
	}
	
	public DragWorkspace(Context context) {
		super(context);
	}
	
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		
		if(mIsFirst) {
			calculateChildCoordinates();
			for(int i = 0; i < mDragLayouts.size(); i ++) {
				int count = mRow * mColumn;
				if(mRow * mColumn * (i + 1) > mChildData.size()) {
					count = mChildData.size() - mRow * mColumn * i;
				}
				for(int j = 0; j < count ; j ++) {
					DataVo dataVo = mChildData.get(mRow * mColumn * i + j);
					dataVo.setPosition(j);
					dataVo.setSourceCoordinate(mChildCoordinates[j][0], mChildCoordinates[j][1]);
					Log.i(TAG, "layout >> " + i + " position >> " + dataVo.getPosition() + 
							": x = " + dataVo.getSourceCoordinate()[0] +
							": y = " + dataVo.getSourceCoordinate()[1] );
				}
			}
			mIsFirst = false;
		}
		
		super.onLayout(changed, l, t, r, b);
	}
	
	/**
	 * 计算出子View的坐标数组
	 */
	private void calculateChildCoordinates() {
		int width = this.getMeasuredWidth();
		int height = this.getMeasuredHeight();
		int childHeight = height / mRow;
		int childWidth = width / mColumn;
		int x = childWidth / 2 - mChildSize / 2;
		int y = childHeight / 2 - mChildSize / 2;
		
		int left = x;
		int top = y;
		
		for(int i = 0; i < mRow; i ++) {
			for(int j = 0; j < mColumn; j ++) {
				mChildCoordinates[i * mColumn + j][0] = left;
				mChildCoordinates[i * mColumn + j][1] = top;
				left += childWidth;
			}
			top += childHeight;
			left = x;
		}
	}

	@Override
	public boolean onLongClick(View v) {
		Log.i(TAG, "onLongClick");
		setShake(true);
		mDragItemView = (DragItemView)v;
		mVibrator.vibrate(20);
		startDrag(mDragItemView);
		return false;
	}
	
	/**
	 * 开始拖曳控件
	 */
	public void startDrag(DragItemView dragView) {
		dragView.setVisibility(View.INVISIBLE);
		mIsDraging = true;
		mLastScreenIndex = mWorkspace.getCurrentScreen();
		
		//获取View的缓存图像
        Rect r = new Rect();
        r.set(dragView.getScrollX(), dragView.getScrollY(), 0, 0);
        offsetDescendantRectToMyCoords(dragView, r);
        boolean willNotCache = dragView.willNotCacheDrawing();
        dragView.setWillNotCacheDrawing(false);
        int color = dragView.getDrawingCacheBackgroundColor();
        dragView.setDrawingCacheBackgroundColor(0);
        if (color != 0) {
        	dragView.destroyDrawingCache();
        }
        dragView.buildDrawingCache();
        Bitmap viewBitmap = dragView.getDrawingCache();
        mBitmapWidth = viewBitmap.getWidth();
        mBitmapHeight = viewBitmap.getHeight();
        
        Matrix scale = new Matrix();
        scale.setScale(1.5f, 1.5f);
        mDragBitmap = Bitmap.createBitmap(viewBitmap, 0, 0, 
        		(int)mBitmapWidth, (int)mBitmapHeight, scale, true);
        mBitmapWidth = mDragBitmap.getWidth();
        mBitmapHeight = mDragBitmap.getHeight();
        dragView.destroyDrawingCache();
        dragView.setWillNotCacheDrawing(willNotCache);
        dragView.setDrawingCacheBackgroundColor(color);
        invalidate();
        mCheckPostionThread = new CheckPostionThread();
        mCheckPostionThread.execute();
	}
	
	/**
	 * 结束拖曳控件
	 */
	public void endDrag() {
		switchPosition();
		mCheckPostionThread.cancel(true);
		mDragItemView.setVisibility(View.VISIBLE);
	}
	
	private void switchPosition() {
		int currentScreen = mWorkspace.getCurrentScreen();
		int position = findPosition((int)mTouchOffsetX, (int)mTouchOffsetY);
		Log.i(TAG, "findPosition : " + position);
		
		if(mLastScreenIndex == currentScreen) {
			mDragLayouts.get(currentScreen).moveTo(mDragItemView, position);
		} else {
			Log.i(TAG, "insert item to other screen");
			mDragLayouts.get(mLastScreenIndex).remove(mDragItemView.getData().getPosition());
			DragItemView overflowView = mDragLayouts.get(currentScreen).insertTo(mDragItemView, position);
			mLastScreenIndex = mWorkspace.getCurrentScreen();
			if(overflowView != null) {
				int count = 0;
				for(int i = currentScreen + 1; count < mDragLayouts.size(); count ++, i++ ) {
					if(i > mDragLayouts.size() - 1) {
						i = 0;
					}
					if(mDragLayouts.get(i).add(overflowView)) {
						break;
					}
				}
			}
		}
	}
	
	/**
	 * 第一次调用invalidate方法都会执行到此方法
	 */
	@Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if(mIsDraging && mDragBitmap != null) {
            final Bitmap dragBitmap = mDragBitmap;
            canvas.save();
            canvas.translate(mTouchOffsetX - mBitmapWidth / 2, mTouchOffsetY - mBitmapHeight / 2);
//            Log.e("canvas:", "mTouchOffsetX:" + mTouchOffsetX + "; mTouchOffsetY:" + mTouchOffsetY);
            canvas.drawBitmap(dragBitmap, 0.0f, 0.0f, mDragPaint);
            canvas.restore();
        }
    }

	/**
	 * 拦截滑动事件
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.i(TAG, "onInterceptTouchEvent");
		mTouchOffsetX = ev.getX();
        mTouchOffsetY = ev.getY();
//		super.onTouchEvent(ev);
		
//		switch(ev.getAction()) {
//		case MotionEvent.ACTION_UP:
//			if (mIsDraging) {
//				onTouchEvent(ev);
//				return false;
//	        }
//		}
//		
		return mIsDraging;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		
		Log.i(TAG, "onTouchEvent");
		mTouchOffsetX = ev.getX();
        mTouchOffsetY = ev.getY();
        
        //判断鼠标位置是否达到屏幕左右边缘，到则触发滚屏事件
        if(!mIsSocrollDelay) {
        	DisplayMetrics dm = new DisplayMetrics();
    		dm = this.getResources().getDisplayMetrics();
    		if(dm.widthPixels <= mTouchOffsetX + TRIGGER_SCROLL_SIZE
    				|| mTouchOffsetX <= TRIGGER_SCROLL_SIZE) {
    			
	    		if(dm.widthPixels <= mTouchOffsetX + TRIGGER_SCROLL_SIZE) {
	    			mWorkspace.scrollRight();
	    		} else {
	    			mWorkspace.scrollLeft();
	    		}
	    		
	    		mIsSocrollDelay = true;
	    		
    			this.postDelayed(new Runnable() {
					@Override
					public void run() {
						mIsSocrollDelay = false;
					}
				}, SCROLL_SCREEN_DELAY);
    		}
        }
        
		//释放则结束拖动的效果
		switch (ev.getAction()) {
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_UP:
        	mIsDraging = false;
        	endDrag();
            break;
      	}
		return true;
	}

	public void setShake(boolean isShake) {
		mIsShake = isShake;
		for(DragItemView child : mChildViews) {
			child.setShake(isShake);
		}
	}
	
	/**
	 * 通过坐标位置查找当前所在的位置索引
	 * @return 当前位置
	 */
	public int findPosition(int x, int y) {
		int childWidth = this.getMeasuredWidth() / mColumn;
		int childHeight = this.getMeasuredHeight() / mRow;
		int currentScreen = mWorkspace.getCurrentScreen();
		int count = mDragLayouts.get(currentScreen).getChildCount();
		int left, top;
		for(int i = 0; i < count; i ++) {
			left = mChildCoordinates[i][0];
			top = mChildCoordinates[i][1];
			if(x >= left && x <= left + childWidth && y >= top && y <= top + childHeight) {
				return i;
			}
		}
		if(currentScreen == mLastScreenIndex) {
			return count - 1;
		} else {
			return count;
		}
	}
	
	/**
	 * 刷新UI线程
	 */
	private AsyncTask<Void, Void, Void> mInvalidateTask = new AsyncTask<Void, Void, Void>() {

		@Override
		protected Void doInBackground(Void... params) {
			try {
				while(true) {
					Thread.sleep(mShakeDelay);
					if(mIsShake) {
						publishProgress((Void)null);
					}
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Void... values) {
			mWorkspace.invalidate();
		}
		
	};
	
	/**
	 * 拖动时调整子View位置线程
	 */
	private class CheckPostionThread extends AsyncTask<Void, Void, Void> {

		@Override
		protected Void doInBackground(Void... params) {
			try {
				while(true) {
					Thread.sleep(DRAG_DELAY);
					publishProgress((Void)null);
				}
			} catch (InterruptedException e) { 
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onProgressUpdate(Void... values) {
			switchPosition();
		}
		
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if(keyCode == KeyEvent.KEYCODE_BACK) {
			if(mIsShake) {
				Log.i(TAG, "onKeyDown");
				setShake(false);
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}
	
	
}
